package ru.jexp.rcp.supply.swtext;

import org.eclipse.core.databinding.observable.value.ValueDiff;
import org.eclipse.core.databinding.property.IProperty;
import org.eclipse.core.databinding.property.ISimplePropertyListener;
import org.eclipse.core.databinding.property.NativePropertyListener;

public class LookupFieldListener<ReturnedT, LookupT extends ILookup<ReturnedT>> extends NativePropertyListener
{

	private IChangeValueListener<ReturnedT> listener;

	public LookupFieldListener(IProperty property, ISimplePropertyListener listener)
	{
		super(property, listener);
	}

	@SuppressWarnings("unchecked")
	@Override
	protected void doAddTo(Object source)
	{
		LookupField<ReturnedT, LookupT> lookup = (LookupField<ReturnedT, LookupT>) source;
		lookup.getLookup().addChangeValueListener(createListener(source));
	}

	@SuppressWarnings("unchecked")
	@Override
	protected void doRemoveFrom(Object source)
	{
		LookupField<ReturnedT, LookupT> lookup = (LookupField<ReturnedT, LookupT>) source;
		lookup.getLookup().removeChangeValueListener(createListener(source));
	}

	private IChangeValueListener<ReturnedT> createListener(final Object source)
	{
		if (listener != null)
		{
			doRemoveFrom(source);
		}
		listener = new InnerChangeValueListener(source);
		return listener;
	}

	private class InnerChangeValueListener implements IChangeValueListener<ReturnedT>
	{
		private final Object source;

		public InnerChangeValueListener(Object source)
		{
			this.source = source;
		}

		@Override
		public void valueChange(final ReturnedT oldValue, final ReturnedT newValue)
		{
			fireChange(source, new ValueDiff()
			{
				@Override
				public Object getOldValue()
				{
					return oldValue;
				}

				@Override
				public Object getNewValue()
				{
					return newValue;
				}
			});
		}
	}
}
